package org.ucas.faker.web.service.fishbone;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.ucas.faker.web.dao.PatentMapper;
import org.ucas.faker.web.fetcher.FetchExecutor;
import org.ucas.faker.web.service.graph.TreeTermService;
import org.ucas.faker.web.service.Visualization.SpecialGraphService;
import org.ucas.faker.web.utils.fishbone.Circle;
import org.ucas.faker.web.utils.fishbone.FishboneNode;
import org.ucas.faker.web.utils.fishbone.FishboneResult;
import org.ucas.faker.web.utils.fishbone.Line;
import org.ucas.faker.web.utils.fishbone.Polygon;
import org.ucas.faker.web.utils.fishbone.Tag;

import java.util.*;

@Service
@Transactional
public class FishboneSimpleService extends FishboneService {

    @Autowired private PatentMapper patentMapper;
    @Autowired private TreeTermService treeTermService;
    @Autowired private FetchExecutor fetcher;
    @Autowired private SpecialGraphService specialGraphService;

    public FishboneResult testSimple(long depotId, long treeId){
        List<HashMap<String, Object>> list = specialGraphService.getPatentInfo(depotId);
        System.out.println("patent list size="+list.size());

        FishboneNode root = constructFishboneList(treeId);

        for (FishboneNode subNode: root.getChildrenList()){
            List<FishboneNode> leafList = subNode.getChildrenList();

            Map<String, Double> tmpWordMap = new HashMap<String, Double>();
            for (int j=0;j<leafList.size();j++){
                String word = leafList.get(j).getTag();
                tmpWordMap.put(word, 0.0);
            }

            for (FishboneNode leaf : leafList){
                int count = 0;
                for (HashMap<String, Object> patentMap : list){
                    if (getWeight(leaf.getTag(), tmpWordMap, patentMap)>3.0){
                        count ++;
                        if (patentMap.containsKey("id")){
                            leaf.addPatent(patentMap.get("id").toString());
                        }
                    }
                }
                leaf.setCount(leaf.getPatentList().size());
            }

            Collections.sort(leafList, new Comparator<FishboneNode>(){
                public int compare(FishboneNode node1, FishboneNode node2) {
                    return node2.getCount() - node1.getCount();
                }
            });

            int length = leafList.size();
            for (int k=length-1;k>=0;k--){
                FishboneNode node = leafList.get(k);
                node.setTag(node.getTag()+"("+node.getCount()+")");
                if (node.getCount()==0){
                    leafList.remove(k);
                }
            }

            length = leafList.size();
            for (int k=length-1;k>=4;k--){
                leafList.remove(k);
            }
        }

        int len = root.getChildrenList().size();

        for (int i=0;i<len;i++){
            int cnt = 0;
            FishboneNode thisNode = root.getChildrenList().get(i);
            for (FishboneNode node : thisNode.getChildrenList()){
                cnt += node.getCount();
                thisNode.addPatent(node.getPatentList());
            }
//            thisNode.setCount(cnt);
            thisNode.setCount(thisNode.getPatentList().size());
            thisNode.setTag(thisNode.getTag()+"("+thisNode.getCount()+")");
        }

        for (int i=len-1;i>=0;i--){
            if (root.getChildrenList().get(i).getChildrenList().size()==0){
                root.getChildrenList().remove(i);
            }
        }

        int total = 0;
        for (FishboneNode node : root.getChildrenList()){
            total += node.getCount();
            root.addPatent(node.getPatentList());
        }
//        root.setCount(total);
        root.setCount(root.getPatentList().size());
        root.setTag(root.getTag()+"("+root.getCount()+")");

        FishboneResult result = drawFishboneSimpleMap(root);
        return result;
    }

    private FishboneResult drawFishboneSimpleMap(FishboneNode root){
        FishboneResult result = new FishboneResult();

        double levelOneStep = 13.0;
        double levelOneRadius = 3.0;
        double levelOneTextSize = 11.0;

        Tag rootTag = new Tag().setX(0).setY(0).setSize(levelOneTextSize).setText(root.getTag()).setDirection(Tag.DIRECTION_LEFT)
                                .setPatentList(root.getPatentList());
        result.addTag(rootTag);

        double levelOneX = 16.0;
        Line rootLine = new Line().setStartPoint(new double[]{0,0}).setEndPoint(new double[]{levelOneX, 0})
                                .setWidth(8.0);
        result.addLine(rootLine);

        //二级节点
        double[] tmpLinePoint = new double[]{levelOneX, 0};
        for (int i=0;i<root.getChildrenList().size();i++){
            double coverLength = levelOneStep*0.9;
            FishboneNode node = root.getChildrenList().get(i);
            double[] startLinePoint = {levelOneX + (i/2)*levelOneStep, 0};
            double[] endLinePoint = {startLinePoint[0]+coverLength, 0+Math.pow(-1, i)*coverLength*1.5};

            /*System.out.println("tag="+node.getTag());
            System.out.println("start: x="+startLinePoint[0]+" y="+startLinePoint[1]);
            System.out.println("end: x="+endLinePoint[0]+" y="+endLinePoint[1]);*/
            Line nodeLine = new Line().setStartPoint(tmpLinePoint).setEndPoint(startLinePoint).setWidth(8.0);
            result.addLine(nodeLine);
            tmpLinePoint = startLinePoint;

            Tag nodeTag = new Tag().setCoordinate(endLinePoint).setSize(levelOneTextSize).setText(node.getTag())
                                .setPatentList(node.getPatentList());
            if (i % 2 == 0) nodeTag.setDirection(Tag.DIRECTION_UP);
            else nodeTag.setDirection(Tag.DIRECTION_DOWN);

            result.addTag(nodeTag);
            nodeTag.print();

            Line line = new Line().setStartPoint(startLinePoint).setEndPoint(endLinePoint);
            result.addLine(line);
            line.print();

            Circle circle = new Circle().setCenter(endLinePoint).setRadius(10);
            result.addCircle(circle);

            //三级节点
            int subNodeNum = node.getChildrenList().size();
            for (int j=0;j<subNodeNum;j++){
                FishboneNode subNode = node.getChildrenList().get(j);
                double lambda = 1.0/(subNodeNum+1.0)*(j+1.0);


                double[] subStartLinePoint = {startLinePoint[0]*lambda+endLinePoint[0]*(1-lambda),
                                              startLinePoint[1]*lambda+endLinePoint[1]*(1-lambda)};

                double[] subEndLinePoint = {subStartLinePoint[0]+levelOneStep*0.8, subStartLinePoint[1]};

                /*System.out.println("subNode tag="+subNode.getTag());
                System.out.println("start: x="+subStartLinePoint[0]+" y="+subStartLinePoint[1]);
                System.out.println("end: x="+subEndLinePoint[0]+" y="+subEndLinePoint[1]);*/

                Tag subTag = new Tag().setCoordinate(subStartLinePoint).setSize(levelOneTextSize).setText(subNode.getTag())
                        .setDirection(Tag.DIRECTION_RIGHT).setPatentList(subNode.getPatentList());
                result.addTag(subTag);
                subTag.print();

                /*Line subLine = new Line().setStartPoint(subStartLinePoint).setEndPoint(subEndLinePoint);
                result.addLine(subLine);
                subLine.print();*/

                Circle subCircle = new Circle().setCenter(subStartLinePoint).setRadius(7);
                result.addCircle(subCircle);

            }
        }

//        System.out.println(tmpLinePoint[0]+"    "+tmpLinePoint[1]);
        result.setBoneEndPoint(tmpLinePoint[0]);
        double[] lastPoint = new double[]{tmpLinePoint[0]+17, tmpLinePoint[1]};
        Line fishtailLine = new Line().setStartPoint(tmpLinePoint).setEndPoint(lastPoint).setWidth(8.0);
        result.addLine(fishtailLine);

        //添加鱼头鱼尾
        Polygon headPolygon = new Polygon()
                .addPoint(new double[]{0,0}).addPoint(new double[]{7.5, 10}).addPoint(new double[]{7.5, -10}).addPoint(new double[]{0,0});
        result.addPolygon(headPolygon);

        double lastX = lastPoint[0]+4;
        Polygon tailPolyton = new Polygon()
                .addPoint(lastPoint).addPoint(new double[]{lastX, 5}).addPoint(new double[]{lastX, -5}).addPoint(lastPoint);
        result.addPolygon(tailPolyton);

        result.setBodyEndPoint(lastX);
        result.setXmax(lastX+2);
        System.out.println("xxx "+result.getXmax());
        return result;
    }

}
